package com.hksj.cm.service;

import cn.hutool.core.collection.CollUtil;
import com.hksj.base.mapper.DefaultDeviceMapper;
import com.hksj.base.query.DeviceOverviewQuery;
import com.hksj.base.service.DefaultDeviceService;
import com.hksj.base.vo.DeviceOverviewVO;
import com.hksj.cbm.service.DeviceInstanceService;
import com.hksj.cbm.vo.DeviceInstanceVO;
import com.hksj.cbm.vo.SpaceModelVO;
import com.hksj.cm.dto.ClLargeScreenDTO;
import com.hksj.cm.mapper.ClLargeScreenMapper;
import com.hksj.cm.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service
public class ClLargeScreenService {

    @Autowired
    private ClLargeScreenMapper clLargeScreenMapper;

    @Autowired
    private DeviceInstanceService deviceInstanceService;

    @Autowired
    private DefaultDeviceMapper defaultDeviceMapper;

    @Autowired
    private DefaultDeviceService defaultDeviceService;


    /**
     * 根据传入的DTO查询清洁等级分布情况。
     *
     * @param dto 查询条件的DTO对象，包含所需查询的参数。
     * @return 返回清洁等级分布的VO列表，包含各个等级的设备数量和占比。
     */
    public List<CleanLevelDistVO> queryCleanLevelDist(ClLargeScreenDTO dto) {
        //生成默认数据
        List<CleanLevelDistVO> defaultList = IntStream.rangeClosed(1, 3)
                .mapToObj(i -> {
                    CleanLevelDistVO cleanLevelDistVO = new CleanLevelDistVO();
                    cleanLevelDistVO.setCleanLevel(String.valueOf(i));
                    return cleanLevelDistVO;
                })
                .collect(Collectors.toList());

        // 根据DTO查询清洁等级分布的VO列表
        List<CleanLevelDistVO> cleanLevelDistVOS = clLargeScreenMapper.queryCleanLevelDist(dto);

        // 非空处理
        if (!CollectionUtils.isEmpty(cleanLevelDistVOS)) {
            // 计算所有等级设备数量的总和
            int total = cleanLevelDistVOS.stream().mapToInt(CleanLevelDistVO::getDeviceNum).sum();

            // 如果总设备数量大于0，计算每个等级的设备数量占比
            if (total > 0) {
                cleanLevelDistVOS.forEach(item -> {
                    item.setDeviceDist(item.getDeviceNum() * 100.0 / total);
                });
            }

            Map<String, CleanLevelDistVO> cleanLevelDistMap = cleanLevelDistVOS.stream()
                    .collect(Collectors.toMap(CleanLevelDistVO::getCleanLevel, item -> item));

            defaultList.forEach(item -> {
               if (cleanLevelDistMap.containsKey(item.getCleanLevel())){
                   item.setDeviceNum(cleanLevelDistMap.get(item.getCleanLevel()).getDeviceNum());
                   item.setDeviceDist(cleanLevelDistMap.get(item.getCleanLevel()).getDeviceDist());
               }
            });
        }

        // 返回计算后的清洁等级分布VO列表
        return defaultList;
    }


    /**
     * 查询清洁度等级排名
     *
     * @param dto 输入参数对象，用于查询清洁度等级排名
     * @return 清洁度等级排名列表
     */
    public List<CleanLevelRankVO> queryCleanLevelRank(ClLargeScreenDTO dto) {
        // 通过输入参数查询清洁度等级排名列表
        List<CleanLevelRankVO> list = clLargeScreenMapper.queryCleanLevelRank(dto);
        // 如果列表为空，则返回空列表
        if (CollUtil.isEmpty(list)) {
            return new ArrayList<>();
        }
        // 提取并转换路径信息为UTF-8格式
        List<String> pathList = list.stream()
                .map(CleanLevelRankVO::getPaths)
                .filter(Objects::nonNull) // 过滤掉空的路径信息
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(pathList)){
            return list;
        }
        // 将设备路径转换为可读的路径名称
        Map<String, List<SpaceModelVO>> pathNameMap = deviceInstanceService.devicePathConvertToUTF8(pathList);
        // 如果路径名称映射不为空，则更新每个排名项的路径信息
        if (CollUtil.isNotEmpty(pathNameMap)) {
            list.forEach(alarmVO -> {
                // 获取路径对应的设备模型列表
                List<SpaceModelVO> spaceModelVOList = pathNameMap.get(alarmVO.getPaths());
                if (CollUtil.isNotEmpty(spaceModelVOList)) {
                    // 根据设备模型的级别对路径名称进行排序和拼接
                    String paths = spaceModelVOList.stream()
                            .sorted(Comparator.comparingInt(SpaceModelVO::getLevel))
                            .map(SpaceModelVO::getModelName)
                            .collect(Collectors.joining("+"));
                    // 更新排名项的路径信息
                    alarmVO.setDeviceLocation(paths);
                }
            });
        }
        // 返回处理后的清洁度等级排名列表
        return list;
    }

    /**
     * 根据屏幕显示选项查询清洁等级日历数据
     *
     * @param dto 屏幕显示数据传输对象，包含查询条件
     * @return 返回清洁等级日历数据列表
     */
    public List<CleanLevelCalendarVO> queryCleanLevelCalendar(ClLargeScreenDTO dto) {
        // 查询设备实例列表
        List<DeviceInstanceVO> list = clLargeScreenMapper.queryCleanLevelCalendarDevice(dto);
        // 如果设备实例列表为空，则直接返回空列表
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        // 提取设备ID列表
        List<String> deviceIdList = list.stream().map(DeviceInstanceVO::getId).collect(Collectors.toList());
        // 初始化存储查询结果的数据列表
        List<CleanLevelCalendarVO> data = new ArrayList<>();
        try {
            // 根据设备实例列表中的第一个设备的productId构造表名
            String tableName = defaultDeviceService.getTableName(list.get(0).getProductId());
            // 使用构造的表名和设备ID列表查询清洁等级日历数据
            data = clLargeScreenMapper.queryCleanLevelCalendar(tableName,deviceIdList,dto);
        } catch (Exception e) {
            // 捕获异常，处理表名不存在的情况
            System.err.println("表名不存在或查询出错: " + e.getMessage());
        }
        // 检查数据列表是否为空
        if (!CollectionUtils.isEmpty(data)) {
            // 使用流操作对数据进行分组，以获取每个日期下最高的清洁级别
            Map<String, CleanLevelCalendarVO> resultMap = data.stream()
                    .collect(Collectors.groupingBy(
                            CleanLevelCalendarVO::getCalendarTime, // 根据日期进行分组
                            Collectors.collectingAndThen(
                                    Collectors.maxBy(Comparator.comparingDouble(CleanLevelCalendarVO::getCleanLevel)), // 在每个日期组内找出清洁级别最高的记录
                                    max -> max.orElse(null) // 如果存在最大值，则返回该记录，否则返回null
                            )
                    ));
            // 将分组后的结果重新设置回data列表
            data = new ArrayList<>(resultMap.values());
        }
        // 返回查询到的数据列表
        return data;
    }

    public Map<String, Object> eqOverviewList(DeviceOverviewQuery dto) {
        DeviceOverviewVO vo = defaultDeviceMapper.getDeviceOverview(dto);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("total", vo.getTotal());
        map.put("offlineNum", vo.getOfflineNum());
        map.put("onlineNum", vo.getOnlineNum());
        map.put("notActiveNum", vo.getNotActiveNum());
        String deviceOnlineRate = "0%";
        // 检查设备总数是否为零
        if (vo.getTotal() == 0) {
            // 设定一个默认值或者返回一个特定的消息
            deviceOnlineRate = "0%";
        } else {
            deviceOnlineRate = vo.getOnlineNum() * 100 / vo.getTotal() + "%";
        }
        map.put("onlineRate", deviceOnlineRate);
        return map;
    }

    public List<DeviceVO> deviceList(ClLargeScreenDTO dto) {
        //查询所有洁净设备
        List<DeviceVO> list = clLargeScreenMapper.deviceList(dto);
        // 使用 Stream API 提取所有 id 并收集到一个新的 List 中
        List<String> collect = list.stream().map(DeviceVO::getId).collect(Collectors.toList());
        //查询所有洁净设备属性值
        List<DeviceMetadataParseInfoVO> deviceListVOS = clLargeScreenMapper.deviceProperty(dto, collect);
        // 创建一个映射，以 DeviceVO 的 ID 作为键，DeviceVO 对象作为值
        Map<String, DeviceVO> deviceById = list.stream()
                .collect(Collectors.toMap(DeviceVO::getId, device -> device));
        // 使用 Stream API 处理 DeviceMetadataParseInfoVO 集合并收集匹配的对象
        Map<String, List<DeviceMetadataParseInfoVO>> matchedMetadataByDeviceId = deviceListVOS.stream()
                .filter(vo -> deviceById.containsKey(vo.getId()))
                .collect(Collectors.groupingBy(DeviceMetadataParseInfoVO::getId));
        // 遍历 DeviceVO 集合，并设置匹配的 DeviceMetadataParseInfoVO 列表
        matchedMetadataByDeviceId.forEach((deviceId, metadataList) -> {
            DeviceVO device = deviceById.get(deviceId);
            device.setDeviceListVOS(metadataList);
        });
        return list;
    }
}
